                    EJECT
*******************************************************************************
*
rrCalcRgns          start
*
* Description:      Calculate the content and structure regions of the window
*                   in Global coordinates.
*
*
* Inputs:           theWindow's portRect and boundsRect will be set
*                   appropriately. NOTE: The strucRgn and contRgn must be
*                   returned in GLOBAL coordinates. However, while the
*                   settings of the portRect and boundsRect show the relative
*                   positioning of the window on the desktop, they do not give
*                   a rectangle in global coordinates on which we can base our
*                   calculations. The routine "GetpRect" shows the correct way
*                   to get a rectangle in global coordinates on which you
*                   should base your calculations.
*
* Outputs:          result =  0
*                   carry  = clear
*                   theWindow.StrucRgn = frame region
*                                       (region handle already allocated)
*                   theWindow.ContRgn = content region
*                                       (region handle already allocated)
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

                    jsr GetpRect        ; get portRect; convert to Globals

;
; Create the rectangle we will use for creating the strucRgn. This is
; calculated based on the portRect, titleHeight, and screen mode.
;

                    ldy #titleHeight    ; Get the suggested height of titlebar
                    lda contRect        ; Raise the height of the strucRect by
                    sec                 ;    that much.
                    sbc [<windGlobals],y
                    sta strucRect

                    lda contRect+4      ; lower bottom of the strucRect by 1
                    ina
                    sta strucRect+4

                    ldy #lineW          ; adjust width of the strucRect based
                    lda contRect+2      ; on the size of the lineWidth
                    sec
                    sbc [<windGlobals],y ; one linewidth on the left...
                    sta strucRect+2

                    lda contRect+6
                    clc
                    adc [<windGlobals],y ; ...and on the right.
                    sta strucRect+6

; now create the Content Region by doing a FrameRRect on the contRect, and
; adding a square region to it. First create a round rect region of the full
; content size.

                    _OpenRgn

                    PushLong #ContRect
                    ldy #owRH           ; these are the radii of the corners
                    lda [<theWindow],y
                    pha
                    ldy #owRV
                    lda [<theWindow],y
                    pha
                    _FrameRRect

                    ldy #owContRgn+2    ; push on the handle of the content
                    lda [<theWindow],y  ; region stored in the window record
                    sta ContRgnHandle+2
                    pha
                    dey
                    dey
                    lda [<theWindow],y
                    sta ContRgnHandle
                    pha
                    _CloseRgn

; Now create a square region to fill in the small upper corners.

                    pha
                    pha
                    _NewRgn
                    PullLong TempRgn

                    _OpenRgn

                    lda ContRect
                    clc
                    ldy #owRV
                    adc [<theWindow],y
                    sta ContRect+4

                    PushLong #ContRect
                    _FrameRect

                    PushLong TempRgn
                    _CloseRgn

; Add the two regions together.

                    PushLong ContRgnHandle
                    PushLong TempRgn
                    PushLong ContRgnHandle
                    _UnionRgn

                    PushLong TempRgn
                    _DisposeRgn

; now create the Structure Region by doing a FrameRRect on the strucRect.

                    _OpenRgn

                    PushLong #strucRect
                    ldy #owRH           ; these are the radii of the corners
                    lda [<theWindow],y
                    pha
                    ldy #owRV
                    lda [<theWindow],y
                    pha
                    _FrameRRect

                    ldy #owStrucRgn+2   ; push on the handle of the structure
                    lda [<theWindow],y  ; region stored in the window record.
                    sta StrucRgnHandle+2
                    pha
                    dey
                    dey
                    lda [<theWindow],y
                    sta StrucRgnHandle
                    pha
                    _CloseRgn

                    clc
                    rts

ContRgnHandle       ds 4
StrucRgnHandle      ds 4
TempRgn             ds 4

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Fetches the portrect from the window record, and converts it to
; global coordinates. It leaves the rectangle in 'pRect' and 'contRect'
;
; LocalToGlobal conversion is done by subtracting boundsRect.y1 from the
; vertical coordinates of portRect, and doing similarly for the horizontal
; coordinates. This is essentially saying "How far away from the top and
; left edges of the screen is the portRect?".
;

GetpRect            ANOP
                    ldy #oPort+oportRect
                    lda [<theWindow],y
                    sec
                    ldy #oPort+oboundsRect
                    sbc [<theWindow],y
                    sta pRect
                    sta contRect

                    ldy #oPort+oportRect+2
                    lda [<theWindow],y
                    sec
                    ldy #oPort+oboundsRect+2
                    sbc [<theWindow],y
                    sta pRect+2
                    sta contRect+2

                    ldy #oPort+oportRect+4
                    lda [<theWindow],y
                    sec
                    ldy #oPort+oboundsRect
                    sbc [<theWindow],y
                    sta pRect+4
                    sta contRect+4

                    ldy #oPort+oportRect+6
                    lda [<theWindow],y
                    sec
                    ldy #oPort+oboundsRect+2
                    sbc [<theWindow],y
                    sta pRect+6
                    sta contRect+6

                    rts

                    end

                    EJECT
*******************************************************************************
*
rrNew               start
*
* Description:
*
* Perform any window record initialization. This routine is should set :
*
*   - the wRefCon, wContDraw, wColors, and wFrameCtls fields.
*   - the fCtlTie, fVis, and fQContent bits in wFrame word.
*   - any other fields in the Custom part of the record.
*
* The following has already been done:
*
*   - a window record has been allocated (as specified by the wNew call).
*   - a port has been opened (as specified by the wPosition call).
*   - handles have been placed in wStrucRgn, wContRgn, and wUpdateRgn.
*   - wContDefProc points to us.
*   - the window has been added to the window list, and wNext field set.
*   - the fAllocated and fHilited bits have been set. All others are zero.
*
* Here is the window record. Asterisks are by the fields we have to set up:
*
*                      0 wNext
*                      4 wPort
*                    174 wDefProc
*                   *178 wRefCon
*                   *182 wContDraw
*                    186 wReserved
*                    190 wStrucRgn
*                    194 wContRgn
*                    198 wUpdateRgn
*                    202 wCtls
*                   *206 wFrameCtls
*                   *210 wFrame
*                   *212 wCustom
*
*
* Inputs:           param  = pointer to parameter list supplied to _NewWindow
*
* Outputs:          result = zero
*                   carry  = clear
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

;
; Set the frame bits based on the _NewWindow parmlist settings.
;
; We only really pay attention to: fClose, fMove.
;
; In addition, Window manager requires: fVis, fQContent, fCtlTie.
;

                    ldy #wFrameBits     ; Get the bits from the parm list.
                    lda [<param],y      ; Make sure we don't affect fAllocated
                    and #$FFFF-fAllocated-fHilited ; or fHilited.

                    ldy #owFrame        ; Get the bits as the WM has them.
                    ora [<theWindow],y  ; Merge his and ours together...
                    sta [<theWindow],y  ; ...and save them.

; copy the wRefCon, wContDraw, and wColors from the parmlist

                    ldy #owRefConVal    ; dest index
                    ldx #wRefCon        ; source index
                    lda #8              ; bytes to move
                    jsr CopyBlock

; Copy all of the custom stuff into the end of the window record

                    ldy #owCustom       ; used as dest index
                    ldx #wCustom        ; used as source index
                    lda #wEnd-wCustom   ; bytes to move
                    jsr CopyBlock

; The frame controls are already zeroed out by the Window manager before
; we get called, so we don't have to initialize that field.


; Finally, calculate the Frame and Content regions

                    jsr rrCalcRgns

                    clc
                    rts


CopyBlock           ANOP
                    sta Count
loop                ANOP
                    phy                 ; save the dest index
                    txy                 ; transfer in the source index
                    lda [<param],y      ; get a source word
                    ply                 ; retrieve the dest index
                    sta [<theWindow],y  ; save the copy
                    iny                 ; bump our indices
                    iny
                    inx
                    inx
                    dec Count           ; are we done?
                    dec Count
                    bne loop            ; no - copy some more

                    rts

Count               ds 2

                    end

                    EJECT
*******************************************************************************
*
rrDispose           start
*
* Description:      Dispose of any additional fields created by the wNew call,
*                   and tell the Window manager whether or not it should
*                   continue the disposal. If we return FALSE, the Window
*                   Manager will:
*
*                   - erase the window from the screen
*                   - remove the window from the window list
*                   - free any controls in wControls and wFrameCtls
*                   - free the strucRgn, contRgn, and updateRgn handles
*                   - close the GrafPort
*                   - release the window record if it was allocated
*                     dynamically (see allocate bit in wFrame field)
*
*
* Inputs:           NONE
*
* Outputs:          to continue disposal: result = FALSE (zero)
*                   to abort disposal:    result = TRUE  (non-zero)
*                   in either case...     carry  = clear
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

                    clc
                    rts
                    end

                    EJECT
*******************************************************************************
*
rrGetDrag           start
*
* Description:      Return the address of the routine that will draw the
*                   outline of the window as it is dragged. You can take the
*                   easy way out and return $0000 0000 in 'result'; that will
*                   tell the window manager take care of matters by dragging
*                   the bounds rectangle of the strucRgn. I use my own routine
*                   which draws a RoundRect.
*
*
* Inputs:           NONE
*
* Outputs:          result = pointer to Drag routine, $0000 0000 for default
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

                    lda #myDrag         ; return the pointer to my routine
                    sta <result
                    lda #^myDrag
                    sta <result+2

                    jsr GetStrucRect    ; get a copy of the rect to drag

                    lda StrucRect       ; make a local copy
                    sta DragRect
                    lda StrucRect+2
                    sta DragRect+2
                    lda StrucRect+4
                    sta DragRect+4
                    lda StrucRect+6
                    sta DragRect+6

                    ldy #owRV           ; get the radii of the corners
                    lda [<theWindow],y
                    sta localRV

                    ldy #owRH
                    lda [<theWindow],y
                    sta localRH

                    clc
                    rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This drag routine will be called with the following parameters:
;
;                   PUSH:WORD - delta X (signed)
;                   PUSH:WORD - delta Y (Your truly,)
;                   PUSH:BYTE[3] - return address

RTLAddr             equ 1
DY                  equ RTLAddr+3
DX                  equ DY+2

myDrag              ANOP
                    clc                 ; offset/copy the original rectangle
                    lda DragRect
                    adc DY,s
                    sta DragRect2

                    clc
                    lda DragRect+2
                    adc DX,s
                    sta DragRect2+2

                    clc
                    lda DragRect+4
                    adc DY,s
                    sta DragRect2+4

                    clc
                    lda DragRect+6
                    adc DX,s
                    sta DragRect2+6

                    pha                 ; save the pen mode
                    _GetPenMode

                    PushWord #modeXOR   ; and change it to XOR
                    _SetPenMode

                    PushLong #DragRect2
                    PushWord localRH
                    PushWord localRV
                    _FrameRRect

                    _SetPenMode         ; restore the old pen mode

                    lda RTLAddr,s       ; move the rtl address back up
                    sta 5,s
                    lda RTLAddr+1,s
                    sta 6,s

                    pla                 ; remove the parameters
                    pla

                    rtl                 ; back to dragrect!


DragRect            ds 8
DragRect2           ds 8
localRH             ds 2
localRV             ds 2

                    end

                    EJECT
*******************************************************************************
*
rrGrowFrame         start
*
* Description:      Draw the outline of the window frame as it is grown. The
*                   easiest way to deal with this routine is to ignore
*                   everything passed to it, and return $0000 in result. This
*                   will grow windows the normal way.
*
*
* Inputs:           'param' points to the following data structure:
*
*        newsize    RECT  Rectangle that defines the new size
*        drawFlag   WORD  TRUE to draw frame, false to erase
*        startRect  RECT  Bounds of wStrucRgn when dragging started.
*        deltaY     WORD  Vertical movement since starting to drag (signed).
*        deltaX     WORD  Horizontal movement since starting to drag (signed).
*
* Outputs:          'result' should have the following bits set or clear:
*
*        0: TRUE if frame was drawn by us, FALSE if default frame is requested.
*        1: TRUE if newSize RECT was changed in a custom fashion, FALSE if not.
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

newSize             equ 0
drawFlag            equ newsize+8
startRect           equ drawFlag+2
deltaY              equ startRect+8
deltaX              equ deltaY+2

;
; param is a pointer to a data block, the first 8 bytes of which
; is the rectangle we want to draw. So push Param on the stack for
; FrameRRect.
;
                    PushLong <param
                    ldy #owRH
                    lda [<theWindow],y
                    pha
                    ldy #owRV
                    lda [<theWindow],y
                    pha
                    _FrameRRect

                    lda #%0001          ; say the we drew the rect but
                    sta <result         ; didn't change it.

                    clc
                    rts
                    end

                    EJECT
*******************************************************************************
*
rrRecSize           start
*
* Description:      Return the size of the window record required by this
*                   defProc. This number is the number of bytes needed beyond
*                   the number normally allocated by the window manager.
*
*                   If you want to indicate that storage has already been
*                   allocated (perhaps a a field was set in the NewWindow
*                   parameter list, like wStorage in the standard window list),
*                   then return the pointer to that record with bit 31 set.
*
*
* Inputs:           param  = pointer to parameter list supplied to _NewWindow
*
* Outputs:          result = number of additional bytes required, or
*                            pointer to window record with the high bit set
*                   carry  = clear
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

; Let's see if there is storage defined in the parameter list

                    ldy #wStorage
                    lda [<param],y
                    iny
                    iny
                    ora [<param],y
                    bne Allocated

; No, so tell the window manager how large it should be

                    lda #owEnd-owCustom
                    sta <result
                    bra done

Allocated           ANOP
                    lda [<param],y      ; Return the high word with the high
                    ora #$8000          ; bit set to tell the WMgr what we did.
                    sta <result+2
                    dey
                    dey
                    lda [<param],y      ; Return the low word normally
                    sta <result

done                ANOP
                    clc
                    rts
                    end

                    EJECT
*******************************************************************************
*
rrPosition          start
*
* Description:      Supply the rectangle to be used as the window's PortRect.
*
*
* Inputs:           param  = pointer to parameter list supplied to _NewWindow
*
* Outputs:          result = pointer to the rect to be used as the PortRect
*                   carry  = clear
*
* External Refs:
*
* Entry Points:
*
*******************************************************************************
                    using RRectDefProcData

; Take the pointer to the parameter list and add the offset to field
; that holds the portrect.

                    ADD4 #wPosition,<param,<result

                    clc
                    rts
                    end

                    EJECT
*******************************************************************************
*
rrBehind            start
*
* Description:      This routine extracts the wPlane value of the parmList
*                   passed to NewWindow and passes it back to the Window
*                   Manager in 'result'. Pass back $FFFF FFFF to always place
*                   the window on top, or $0000 0000 to place the window on the
*                   bottom.
*
*
* Inputs:           param  = pointer to parameter list passed to _NewWindow
*
* Outputs:          result = window pointer, $FFFF FFFF, or $0000 0000
*                   carry  = clear
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

                    ldy #wPlane         ; simply get what was specified in
                    lda [<param],y      ; the parameter list supplied to
                    sta <result         ; _NewWindow (since we are the only
                    iny                 ; one who knows where is it) and return
                    iny                 ; it to the Window Manager.
                    lda [<param],y
                    sta <result+2

                    clc
                    rts
                    end

                    EJECT
*******************************************************************************
*
rrCallDefProc       start
*
* Description:      Generic call to the defProc. Through this, the Window
*                   Manager can access the fields in the custom window's
*                   data in response to the many Get/Set calls.
*
*
* Inputs:           On entry, 'param' points to the following block of data:
*
*                   WORD : dRequest     Requested operation number
*                   WORD : paramID      Parameter block type:
*                                         $0000-7FFF reserved by system
*                                         $8000-FFFF reserved for application
*                                         (We only handle type $0000 System
*                                          in this sample)
*                   XXXX : newParam     Operation specific data
*
* Outputs:          Call specific. See technote for more details.
*
* External Refs:
*                   Import rrSetTitle
*                   Import rrSetColor
*                   Import rrSetFrame
*                   Import rrGetTitle
*                   Import rrGetColor
*                   Import rrGetFrame
*                   Import handleWTask
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

dRequest            equ 0
paramID             equ dRequest+2
newParam            equ paramID+2

MaxDRequest         equ 33

                    ldy #paramID        ; Do we know this paramID type?
                    lda [<param],y
                    bne ignore          ; $0000, ignore all others

                    lda [<param]        ; dRequest
                    cmp #MaxDRequest+1  ; is this request in range?
                    bcs ignore          ; no so leave
                    asl a               ; yes, turn into index into proc table
                    tax
                    jmp (dRequestTable,x)

dRequestTable       ANOP
                    dc i2'ignore'       ;  0 wSetOrgmask
                    dc i2'ignore'       ;  1 wSetMaxGrow
                    dc i2'ignore'       ;  2 wSetScroll
                    dc i2'ignore'       ;  3 wSetPage
                    dc i2'ignore'       ;  4 wSetInfoRefCon
                    dc i2'ignore'       ;  5 wSetInfoDraw
                    dc i2'ignore'       ;  6 wSetOrigin
                    dc i2'ignore'       ;  7 wSetDataSize
                    dc i2'ignore'       ;  8 wSetZoomRect
                    dc i2'rrSetTitle'   ;  9 wSetTitle
                    dc i2'rrSetColor'   ; 10 wSetColorTable
                    dc i2'rrSetFrame'   ; 11 wSetFrameFlag
                    dc i2'ignore'       ; 12 wGetOrgMask
                    dc i2'ignore'       ; 13 wGetMaxGrow
                    dc i2'ignore'       ; 14 wGetScroll
                    dc i2'ignore'       ; 15 wGetPage
                    dc i2'ignore'       ; 16 wGetInfoRefCon
                    dc i2'ignore'       ; 17 wGetInfoDraw
                    dc i2'ignore'       ; 18 wGetOrigin
                    dc i2'ignore'       ; 19 wGetDataSize
                    dc i2'ignore'       ; 20 wGetZoomRect
                    dc i2'rrGetTitle'   ; 21 wGetTitle
                    dc i2'rrGetColor'   ; 22 wGetColorTable
                    dc i2'rrGetFrame'   ; 23 wGetFrameFlag
                    dc i2'ignore'       ; 24 wGetInfoRect
                    dc i2'ignore'       ; 25 wGetDrawInfo
                    dc i2'ignore'       ; 26 wGetStartInfoDraw
                    dc i2'ignore'       ; 27 wGetEndInfoDraw
                    dc i2'ignore'       ; 28 wZoomWindow
                    dc i2'ignore'       ; 29 wStartDrawing
                    dc i2'rrStartMove'  ; 30 wStartMove (defined in this PROC)
                    dc i2'ignore'       ; 31 wStartGrow
                    dc i2'rrNewSize'    ; 32 wNewSize (defined in this PROC)
                    dc i2'handleWTask'  ; 33 wTask

rrStartMove         ldy #newParam+2     ; Preparing to move the window. Examine
                    lda [<param],y      ; the proposed destination rectangle
                    sta <result+2       ; and see if it is OK. If it is, simply
                    dey                 ; return it. If it isn't, then change
                    dey                 ; it. We will like it, so we'll just
                    lda [<param],y      ; return what we get.
                    sta <result
                    clc
                    rts

rrNewSize           ANOP
                    lda #1              ; Always return TRUE. This tells the
                    sta <result         ; window manager to redraw only
                    clc                 ; uncovered contents.
                    rts

ignore              clc
                    rts

                    end

                    EJECT
*******************************************************************************
*
handleWTask         start
*
* Description:      Called to handle FindWindow results passed on by
*                   TaskMaster. Since TaskMaster only handles event that occur
*                   in menus and system windows, custom window defprocs must
*                   handle all of the rest. These include:
*
*                   wInContent          wInDrag
*                   wInGrow             wInGoAway
*                   wInZoom             wInInfo
*                   wInFrame
*
*
* Inputs:           'param' points to the following block of data:
*
*                   WORD:dRequest       = 33 for wTask
*                   WORD:paramID        we only handle type $0000 System calls
*                   LONG:newParam       Pointer to Task Record
*                   WORD:newParam       result from FindWindow
*
* Outputs:          'result' equals the following:
*
*                                       Low Word            High Word
*                                       -----------------   -------------------
*    If the event was handled:          Zero                Action taken
*    If the event was not handled:      FindWindow result   ignored
*
* External Refs:    NONE
*
* Entry Points:     NONE
*
*******************************************************************************
                    using RRectDefProcData

dRequest            equ 0
paramID             equ dRequest+2
newParam            equ paramID+2
TaskRecPtr          equ newParam
FWResult            equ TaskRecPtr+4

TaskRec             equ work

                    ldy #TaskRecPtr+2   ; get the pointer to the Event Record
                    lda [<param],y      ; into 'TsskRec', aka 'work'.
                    sta <TaskRec+2
                    dey
                    dey
                    lda [<param],y
                    sta <TaskRec

                    ldy #FWResult       ; get the Findwindow result
                    lda [<param],y

                    sec                 ; turn it into an index
                    sbc #wInContent
                    bcc callIgnore      ; out of range, so ignore
                    cmp #wInFrame-wInContent+1
                    bcc doit
callIgnore          lda #wInSpecial-wInContent+1
doit                asl a
                    tax
                    jmp (wTaskTable,x)

wTaskTable          dc i2'doInContent'  ; doInContent
                    dc i2'doInDrag'     ; doInDrag
                    dc i2'ignoreTask'   ; doInGrow
                    dc i2'doInGoAway'   ; doInGoAway
                    dc i2'ignoreTask'   ; doInZoom
                    dc i2'ignoreTask'   ; doInInfo
                    dc i2'ignoreTask'   ; doInSpecial (default ignore)
                    dc i2'ignoreTask'   ; doInDeskItem (not used)
                    dc i2'doInContent'  ; doInFrame

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TaskMaster needs us to handle a wInContent event. Check the TaskMask
; field to see if the application wants us to handle it. If so, bring the
; window to front. Then check to see if the application wants to know what
; we just did. If so, return wInContent. If not, return null.

doInContent         ANOP
                    ldy #owmTaskMask    ; do we handle clicks in the content?
                    lda [<TaskRec],y
                    and #tmContent
                    bne Bogus0010       ; yes - just select the window
                    brl ignoreTask      ; no - so pretend we weren't here.

Bogus0010           jsr mySelectWindow

                    ldy #owFrame        ; do we tell the app what we did?
                    lda [<theWindow],y
                    and #fQContent
                    beq Passively       ; no - just return a nullEvt

                    ldx #0
                    lda #wInContent     ; pass this on to the application
                    brl Exit
Passively           ANOP
                    ldx #wInContent     ; This is what we did.
                    lda #0              ; Signal that event was handled
                    brl Exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TaskMaster needs us to handle a wInDrag event. Check the TaskMask
; field to see if the application wants us to handle it. If so, call
; DragWindow with the same parameters described in the TaskMaster
; psuedo-code in the ToolBox Reference. Then check to see if the Apple
; key was down. If it wasn't, bring the window forward. Finally, return
; null.
;
doInDrag            ANOP
                    ldy #owmTaskMask    ; do we do drags?
                    lda [<TaskRec],y
                    and #tmDragW
                    bne Bogus0020       ; yes - get on with it.
                    brl ignoreTask      ; no - so pretend we weren't here.
Bogus0020           ANOP
                    PushWord #0         ; drag resolution
                    ldy #owmWhere+2     ; global coord of cursor
                    lda [<TaskRec],y ; first X
                    pha
                    dey
                    dey
                    lda [<TaskRec],y ; then Y
                    pha
                    PushWord #8         ; grace buffer around bounds
                    PushLong #0         ; default cursor boundary
                    ldy #owmTaskData+2  ; push on window's grafport
                    lda [<TaskRec],y
                    pha
                    dey
                    dey
                    lda [<TaskRec],y
                    pha
                    _DragWindow         ; Call DrawWindow ourselves

                    ldy #owmModifiers   ; if the Apple Key is down then
                    lda [<TaskRec],y     ; don't bring the window to front
                    and #appleKey
                    bne doneDrag

                    jsr mySelectWindow
doneDrag            ANOP
                    ldx #wInDrag        ; This is what we did.
                    lda #0              ; Signal that event was handled
                    bra exit            ; Exit the DefProc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TaskMaster needs us to handle a wInGoAway event. Check the TaskMask
; field to see if the application wants us to handle it. If so, call
; TrackGoAway. If it returns TRUE, then return wInGoAway to the
; application. If it returns FALSE, return wNoHit.
;
doInGoAway          ANOP
                    pha                 ; space for boolean result
                    ldy #owmWhere+2     ; global coord of cursor
                    lda [<TaskRec],y ; first X
                    pha
                    dey
                    dey
                    lda [<TaskRec],y ; then Y
                    pha
                    ldy #owmTaskData+2  ; push on window's grafport
                    lda [<TaskRec],y
                    pha
                    dey
                    dey
                    lda [<TaskRec],y
                    pha
                    _TrackGoAway
                    pla
                    beq noClose

                    ldx #0              ; Close selected. Tell app that we
                    lda #wInGoAway      ; clicked in the goAway box.
                    bra Exit
noClose             ANOP
                    ldx #wInGoAway      ; Close not selected. Tell the app that
                    lda #wNoHit         ; we tracked it, but that everything is
                    bra Exit            ; OK now.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Local routine to bring the window forward if we need to.
;
mySelectWindow      ANOP
                    pei <theWindow+2    ; get the pointer to the window so that
                    clc                 ; we can  bring it to front.
                    lda <theWindow
                    adc #4
                    pha

                    _SelectWindow
                    rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; For some reason, we need to ignore a task. Either we were asked to handle
; an event we know nothing about, or the TaskMask prohibited us from 
; handling a certain event. This routine simply echos the result found by
; FindWindow back to the application.

ignoreTask          ldy #FWResult       ; ignore by echoing the FindWindow
                    lda [<param],y      ;   result.
                    ldx #0              ; fall through to Exit.

Exit                ANOP
                    sta <result         ; TaskMaster result on the stack
                    stx <result+2       ; Low word of TaskData

                    clc
                    rts
                    end

                    EJECT
*******************************************************************************
*
HouseKeeping        start
*
* Description:      Housekeeping calls. Set and get various fields. These will
*                   redraw the window if necessary.
*
*
* Inputs:
*
* Outputs:
*
* External Refs:
*                   Import drawFrame
*
* Entry Points:
*                   entry rrSetTitle
*                   entry rrSetColor
*                   entry rrSetFrame
*                   entry rrGetTitle
*                   entry rrGetColor
*                   entry rrGetFrame
*
*******************************************************************************
                    using RRectDefProcData

dRequest            equ 0
paramID             equ dRequest+2
newParam            equ paramID+2


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrSetTitle          entry
                    ldy #owTitle+2
                    bra SetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrSetColor          entry
                    ldy #owColorPtr+2
                    bra SetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrSetFrame          entry
                    ldy #owFrame
                    bra SetWord

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrGetTitle          entry
                    ldy #owTitle+2
                    bra GetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrGetColor          entry
                    ldy #owColorPtr+2
                    bra GetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrGetFrame          entry
                    ldy #owColorPtr
                    bra GetWord

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SetLong             ANOP
                    phy
                    ldy #newParam+2
                    lda [<param],y
                    ply
                    sta [<theWindow],y
                    dey
                    dey
SetWord             phy
                    lda #newParam
                    lda [<param],y
                    ply
                    sta [<theWindow],y

                    pei <theWindow+2    ; Now redraw the window frame
                    pei <theWindow
                    _StartFrameDrawing  ; must be called by defproc

                    jsr drawFrame

                    _EndFrameDrawing    ; reverses StartFrameDrawing call

                    clc
                    rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Called by the rrGetxxxxx routines above. Enter with Y holding the
; offset to a LONG parameter in the window record. This routine will
; fetch that value and put it into 'result'.
;

GetLong             ANOP
                    lda [<theWindow],y
                    sta <result+2
                    dey
                    dey
GetWord             lda [<theWindow],y
                    sta <result
                    clc
                    rts
                    end
                    
